/*
 * Copyright 2002-2006 the original author or authors. Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License. You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific language governing permissions and limitations under the
 * License.
 */
package pikes.xml;

import java.io.IOException;
import java.io.StringWriter;

import org.custommonkey.xmlunit.XMLTestCase;

import pikes.core.Printable;
import pikes.xml.XMLMarkup;
import pikes.xml.XMLTag;
import pikes.xml.XMLVisitingException;
import pikes.xml.XMLVisitor;
import pikes.xml.XMLWriter;

public class XMLTagTestCase extends XMLTestCase {

	public void testCreate1() throws Exception {
		try {
			new XMLTag(null);
			fail();
		}
		catch (Exception e) {
			// left intentionally empty
		}

	}

	public void testCreate2() throws Exception {
		try {
			new XMLTag("  ");
			fail();
		}
		catch (Exception e) {
			// left intentionally empty
		}

	}

	public void testPrint1() throws Exception {
		XMLTag tag = new XMLTag("name");
		StringWriter writer = new StringWriter();
		tag.print(writer);
		String actual = writer.toString();
		assertEquals("<name/>", actual);
	}

	public void testPrint1WithPrefix() throws Exception {
		XMLTag tag = new XMLTag("prefix", "name");
		StringWriter writer = new StringWriter();
		tag.print(writer);
		String actual = writer.toString();
		assertEquals("<prefix:name/>", actual);
	}

	public void testPrint11() throws Exception {
		XMLTag tag = new XMLTag("name");
		StringWriter writer = new StringWriter();
		XMLWriter xmlWriter = new XMLWriter(writer, false);
		tag.visit(xmlWriter);
		String actual = writer.toString();
		assertEquals("<name/>", actual);
	}

	public void testPrint12() throws Exception {
		XMLTag tag = new XMLTag("name");
		StringWriter writer = new StringWriter();
		XMLWriter xmlWriter = new XMLWriter(writer, true);
		tag.visit(xmlWriter);
		String actual = writer.toString();
		assertEquals("<name></name>", actual);
	}

	public void testProcess() throws Exception {
		XMLTag tag = new XMLTag("name");
		MockXMLProcessor processor = new MockXMLProcessor();
		tag.visit(processor);

		assertEquals("name", processor.firstName);
		assertFalse(processor.hasChildren);
	}

	public void testProcessWithPrefix() throws Exception {
		XMLTag tag = new XMLTag("prefix", "name");
		MockXMLProcessor processor = new MockXMLProcessor();
		tag.visit(processor);

		assertEquals("name", processor.firstName);
		assertEquals("prefix", processor.prefix);
		assertFalse(processor.hasChildren);
	}

	public void testPrintAttributes00() throws Exception {
		XMLTag tag = new XMLTag("name");
		tag.addAttribute("name", "value");
		StringWriter writer = new StringWriter();
		XMLVisitor xmlWriter = new XMLWriter(writer);
		tag.visit(xmlWriter);
		String actual = writer.toString();
		assertEquals("<name name=\"value\"/>", actual);
	}

	public void testPrintAttributes01() throws Exception {
		XMLTag tag = new XMLTag("name");
		tag.addAttribute("name", new Printable() {

			public void print(Appendable appendable) throws IOException {
				appendable.append("value");
			}

		});
		StringWriter writer = new StringWriter();
		XMLVisitor xmlWriter = new XMLWriter(writer);
		tag.visit(xmlWriter);
		String actual = writer.toString();
		assertEquals("<name name=\"value\"/>", actual);
	}

	public void testPrintAttributes11() throws Exception {
		XMLTag tag = new XMLTag("name");
		tag.addAttribute("name", "value");
		StringWriter writer = new StringWriter();
		XMLVisitor xmlWriter = new XMLWriter(writer, false);
		tag.visit(xmlWriter);
		String actual = writer.toString();
		assertEquals("<name name=\"value\"/>", actual);
	}

	public void testPrintAttributes12() throws Exception {
		XMLTag tag = new XMLTag("name");
		tag.addAttribute("name", new Printable() {
			public void print(Appendable appendable) throws IOException {
				appendable.append("value");
			}
		});
		StringWriter writer = new StringWriter();
		XMLVisitor xmlWriter = new XMLWriter(writer, false);
		tag.visit(xmlWriter);
		String actual = writer.toString();
		assertEquals("<name name=\"value\"/>", actual);
	}

	public void testPrintAttributes21() throws Exception {
		XMLTag tag = new XMLTag("name");
		tag.addAttribute("name", "value");
		StringWriter writer = new StringWriter();
		XMLVisitor xmlWriter = new XMLWriter(writer, true);
		tag.visit(xmlWriter);
		String actual = writer.toString();
		assertEquals("<name name=\"value\"></name>", actual);
	}

	public void testPrintAttributes22() throws Exception {
		XMLTag tag = new XMLTag("name");
		tag.addAttribute("name", new Printable() {
			public void print(Appendable appendable) throws IOException {
				appendable.append("value");
			}
		});
		StringWriter writer = new StringWriter();
		XMLVisitor xmlWriter = new XMLWriter(writer, true);
		tag.visit(xmlWriter);
		String actual = writer.toString();
		assertEquals("<name name=\"value\"></name>", actual);
	}

	public void testPrintChildTag() throws Exception {
		XMLTag tag = new XMLTag("name");
		tag.addTag(new XMLTag("child"));
		StringWriter writer = new StringWriter();
		XMLVisitor xmlWriter = new XMLWriter(writer);
		tag.visit(xmlWriter);
		String actual = writer.toString();
		assertEquals("<name><child/></name>", actual);
	}

	public void testPrintChildTag1() throws Exception {
		XMLTag tag = new XMLTag("name");
		tag.addTag(new XMLTag("child"));
		StringWriter writer = new StringWriter();
		XMLVisitor xmlWriter = new XMLWriter(writer, false);
		tag.visit(xmlWriter);
		String actual = writer.toString();
		assertEquals("<name><child/></name>", actual);
	}

	public void testPrintChildTag2() throws Exception {
		XMLTag tag = new XMLTag("name");
		tag.addTag(new XMLTag("child"));
		StringWriter writer = new StringWriter();
		XMLVisitor xmlWriter = new XMLWriter(writer, true);
		tag.visit(xmlWriter);
		String actual = writer.toString();
		assertEquals("<name><child></child></name>", actual);
	}

	public void testPrintChildText() throws Exception {
		XMLTag tag = new XMLTag("name");
		tag.addText("subText");
		StringWriter writer = new StringWriter();
		XMLVisitor xmlWriter = new XMLWriter(writer);
		tag.visit(xmlWriter);
		String actual = writer.toString();
		assertXMLEqual("<name>subText</name>", actual);
	}

	public void testPrintChildText1() throws Exception {
		XMLTag tag = new XMLTag("name");
		tag.addText(new Printable() {

			public void print(Appendable appendable) throws IOException {
				appendable.append("subText");

			}

		});
		StringWriter writer = new StringWriter();
		XMLVisitor xmlWriter = new XMLWriter(writer);
		tag.visit(xmlWriter);
		String actual = writer.toString();
		assertXMLEqual("<name>subText</name>", actual);
	}

	public void testPrintComment() throws Exception {
		XMLTag tag = new XMLTag("name");
		tag.addComment("comment");
		StringWriter writer = new StringWriter();
		XMLVisitor xmlWriter = new XMLWriter(writer);
		tag.visit(xmlWriter);
		String actual = writer.toString();
		assertXMLEqual("<name><!-- comment --></name>", actual);
	}

	public void testEqualsWithTheSameNames() throws Exception {
		XMLTag tag1 = new XMLTag("name");
		XMLTag tag2 = new XMLTag("name");
		assertEquals(tag1, tag2);
	}

	public void testDoesNotEqualsWithDifferentNames() throws Exception {
		XMLTag tag1 = new XMLTag("name");
		XMLTag tag2 = new XMLTag("name1");
		assertFalse(tag1.equals(tag2));
	}

	public void testDoesNotEqualsWithSameNamesButDifferentAttributeNumber() throws Exception {
		XMLTag tag1 = new XMLTag("name");
		tag1.addAttribute("a", "b");
		XMLTag tag2 = new XMLTag("name");
		assertFalse(tag1.equals(tag2));
	}

	public void testDoesNotEqualsWithSameNamesButDifferentAttributes() throws Exception {
		XMLTag tag1 = new XMLTag("name");
		tag1.addAttribute("a", "b");
		XMLTag tag2 = new XMLTag("name");
		tag2.addAttribute("a1", "b");
		assertFalse(tag1.equals(tag2));
	}

	public void testEqualsWithSameNamesAndSameAttributes() throws Exception {
		XMLTag tag1 = new XMLTag("name");
		tag1.addAttribute("a", "b");
		XMLTag tag2 = new XMLTag("name");
		tag2.addAttribute("a", "b");
		assertTrue(tag1.equals(tag2));
	}

	public void testDoesNotEqualsWithSameNamesAndSameAttributes() throws Exception {
		XMLTag tag1 = new XMLTag("name");
		tag1.addAttribute("a", "b");
		XMLTag tag2 = new XMLTag("name");
		tag2.addAttribute("a", "b1");
		assertFalse(tag1.equals(tag2));
	}

	public void testDoesNotEqualsWithSameNamesAndSameAttributesButDifferentChildren() throws Exception {
		XMLTag tag1 = new XMLTag("name");
		tag1.addAttribute("a", "b");
		tag1.addChild(new XMLMarkup() {

			public void visit(XMLVisitor xmlWriter) throws XMLVisitingException {
				// TODO Auto-generated method stub

			}

			@Override
			public boolean equals(Object obj) {

				return false;
			}

			public void print(Appendable appendable) throws IOException {
				// TODO Auto-generated method stub

			}
		});
		XMLTag tag2 = new XMLTag("name");
		tag2.addAttribute("a", "b");
		assertFalse(tag1.equals(tag2));
	}

	public void testEqualsWithSameNamesAndSameAttributesButDifferentChildren() throws Exception {
		XMLTag tag1 = new XMLTag("name");
		tag1.addAttribute("a", "b");
		tag1.addChild(new XMLMarkup() {

			public void visit(XMLVisitor xmlWriter) throws XMLVisitingException {
				// TODO Auto-generated method stub

			}

			@Override
			public boolean equals(Object obj) {

				return true;
			}

			public void print(Appendable appendable) throws IOException {
				// TODO Auto-generated method stub

			}
		});
		XMLTag tag2 = new XMLTag("name");
		tag2.addAttribute("a", "b");
		tag2.addChild(new XMLMarkup() {

			public void visit(XMLVisitor xmlWriter) throws XMLVisitingException {
				// TODO Auto-generated method stub

			}

			@Override
			public boolean equals(Object obj) {

				return false;
			}

			public void print(Appendable appendable) throws IOException {
				// TODO Auto-generated method stub

			}
		});
		assertTrue(tag1.equals(tag2));
	}

	public void testEquality() throws Exception {
		XMLTag expected1 = new XMLTag("title");
		expected1.addAttribute("dir", "ltr");
		expected1.addText("boo");

		XMLTag expected2 = new XMLTag("title");
		expected2.addAttribute("dir", "ltr");
		expected2.addText("boo");

		assertEquals(expected1, expected2);
	}
}
